// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


// Adapted from Apache Arrow.

#pragma once

#include <cstdint>
#include <string>

namespace kumo::pollux::parquet {
    struct ByteArray {
        ByteArray() : len(0), ptr(nullptr) {
        }

        ByteArray(uint32_t len, const uint8_t *ptr) : len(len), ptr(ptr) {
        }

        ByteArray(::std::string_view view) // NOLINT implicit conversion
            : ByteArray(
                static_cast<uint32_t>(view.size()),
                reinterpret_cast<const uint8_t *>(view.data())) {
        }

        explicit operator std::string_view() const {
            return std::string_view{reinterpret_cast<const char *>(ptr), len};
        }

        uint32_t len;
        const uint8_t *ptr;
    };

    // Abstract class for hash
    class Hasher {
    public:
        /// Compute hash for 32 bits value by using its plain encoding result.
        ///
        /// @param value the value to hash.
        /// @return hash result.
        virtual uint64_t hash(int32_t value) const = 0;

        /// Compute hash for 64 bits value by using its plain encoding result.
        ///
        /// @param value the value to hash.
        /// @return hash result.
        virtual uint64_t hash(int64_t value) const = 0;

        /// Compute hash for float value by using its plain encoding result.
        ///
        /// @param value the value to hash.
        /// @return hash result.
        virtual uint64_t hash(float value) const = 0;

        /// Compute hash for double value by using its plain encoding result.
        ///
        /// @param value the value to hash.
        /// @return hash result.
        virtual uint64_t hash(double value) const = 0;

        /// Compute hash for ByteArray value by using its plain encoding result.
        ///
        /// @param value the value to hash.
        /// @return hash result.
        virtual uint64_t hash(const ByteArray *value) const = 0;

        /// Batch compute hashes for 32 bits values by using its plain encoding
        /// result.
        ///
        /// @param values a pointer to the values to hash.
        /// @param num_values the number of values to hash.
        /// @param hashes a pointer to the output hash values, its length should be
        /// equal to num_values.
        virtual void hashes(const int32_t *values, int num_values, uint64_t *hashes)
        const = 0;

        /// Batch compute hashes for 64 bits values by using its plain encoding
        /// result.
        ///
        /// @param values a pointer to the values to hash.
        /// @param num_values the number of values to hash.
        /// @param hashes a pointer to the output hash values, its length should be
        /// equal to num_values.
        virtual void hashes(const int64_t *values, int num_values, uint64_t *hashes)
        const = 0;

        /// Batch compute hashes for float values by using its plain encoding result.
        ///
        /// @param values a pointer to the values to hash.
        /// @param num_values the number of values to hash.
        /// @param hashes a pointer to the output hash values, its length should be
        /// equal to num_values.
        virtual void hashes(const float *values, int num_values, uint64_t *hashes)
        const = 0;

        /// Batch compute hashes for double values by using its plain encoding result.
        ///
        /// @param values a pointer to the values to hash.
        /// @param num_values the number of values to hash.
        /// @param hashes a pointer to the output hash values, its length should be
        /// equal to num_values.
        virtual void hashes(const double *values, int num_values, uint64_t *hashes)
        const = 0;

        /// Batch compute hashes for ByteArray values by using its plain encoding
        /// result.
        ///
        /// @param values a pointer to the values to hash.
        /// @param num_values the number of values to hash.
        /// @param hashes a pointer to the output hash values, its length should be
        /// equal to num_values.
        virtual void hashes(const ByteArray *values, int num_values, uint64_t *hashes)
        const = 0;

        virtual ~Hasher() = default;
    };
} // namespace kumo::pollux::parquet
